"use strict";
const FM = require("../handler/FoodManager");
const SM = require("../handler/SnakeMamager");

const Snake = SM.Snake;
const SnakeSet = SM.SnakeSet;
const SnakeSetManager = SM.SnakeSetManager;
const snakeMap = new Map();
const range_width = FM.range_width;
const range_height = FM.range_height;
const unit_range_width = FM.unit_range_width;
const unit_range_height = FM.unit_range_height;
const Food = FM.Food;
const food_set_manager = FM.food_set_manager;

module.exports = function(app) {
	return new SnakeRemote(app);
};

function SnakeRemote(app) {
	this.app = app;
	this.channelService = app.get('channelService');
};
const SnakeRemoteProto = SnakeRemote.prototype;
SnakeRemoteProto.add = function(snake_info, x, y, cb) {
	var new_snake = new Snake(snake_info, x, y);
	snakeMap.set(new_snake.id, new_snake);
	cb && cb(new_snake);
}
SnakeRemoteProto.get = function(uid, cb) {
	cb && cb(snakeMap.get(uid));
}
SnakeRemoteProto.set = function(uid, snake_info, cb) {
	this.get(uid, (snake) => {
		if (snake) {
			snake.destroy();
			snake.importData(snake_info);
		} else {
			snake = new Snake(snake_info, range_width / 2 + 1000 * (Math.random() - 0.5), range_height / 2 + 1000 * (Math.random() - 0.5))
		}
		snakeMap.set(uid, snake);
		cb && cb(snake);
	});
}
SnakeRemoteProto.remove = function(uid, cb) {
	this.get(uid, (snake) => {
		if (snake) {
			snake.destroy();
		}
		cb && cb(snake && snake.id);
	});
}
SnakeRemoteProto.getOther = function(current_uid, cb) {
	var snakes = snakeMap.values();
	var res = [];
	for (var snake of snakes) {
		if (snake.id !== current_uid) {
			res.push(snake)
		}
	}
	cb && cb(res);
}
SnakeRemoteProto.die = function(uid, cb) {
	this.get(uid, (my_snake) => {
		if (my_snake) {
			var food_info_list = my_snake.die();
			var channel = this.channelService.getChannel(my_snake.rid, false);
			food_info_list.forEach(food => food_set_manager.addFood(food));

			channel.pushMessage('dieSnake', {
				foods: food_info_list,
				snake_id: my_snake.id
			});
			snakeMap.delete(uid);
			cb && cb(food_info_list);
		} else {
			cb && cb(false)
		}
	});
}
SnakeRemoteProto.turnHead = function(uid, deg, cb) {
	this.get(uid, (my_snake) => {
		if (my_snake) {
			my_snake.turnHead(deg);
			var channel = this.channelService.getChannel(my_snake.rid, false);
			channel.pushMessage('turnHead', my_snake);
		}
		cb && cb(my_snake);
	});
}

SnakeRemoteProto.sprint = function(uid, cb) {
	this.get(uid, (my_snake) => {
		if (my_snake) {
			const channel = this.channelService.getChannel(my_snake.rid, false);
			var _is_sprinted = my_snake.sprint((burn_body) => {
				let tail_point = my_snake.points[0];
				let food = new Food(Math.round(tail_point.x), Math.round(tail_point.y), {
					add_body: burn_body
				});
				const session = this.app.backendSessionService;
				this.app.rpc.chat.foodRemote.addFoods(session, [food], function() {});
				channel.pushMessage('burnSnake', {
					foods: [food],
					snake_id: my_snake.id,
					burn_body: burn_body
				});
			}, () => {
				channel.pushMessage("snakeStopSprint", my_snake);
			});
			channel.pushMessage('snakeSprint', my_snake);
		}
		cb && cb(_is_sprinted);
	});
}

SnakeRemoteProto.stopSprint = function(uid, cb) {
	this.get(uid, (my_snake) => {
		if (my_snake) {
			var _is_stop_sprint = my_snake.stopSprint();
			const channel = this.channelService.getChannel(my_snake.rid, false);
			if (_is_stop_sprint) {
				channel.pushMessage("snakeStopSprint", my_snake);
			}
		}
		cb && cb(_is_stop_sprint);
	});
}